package com.starblink.android.basic.network.testfunction

import android.os.Build
import com.apollographql.apollo3.api.ApolloRequest
import com.apollographql.apollo3.api.ApolloResponse
import com.apollographql.apollo3.api.Operation
import com.apollographql.apollo3.network.http.HttpInfo
import com.blankj.utilcode.util.AppUtils
import com.blankj.utilcode.util.EncodeUtils
import com.blankj.utilcode.util.NetworkUtils
import com.blankj.utilcode.util.ScreenUtils
import com.google.gson.JsonObject
import com.google.gson.JsonParser
import com.starblink.android.basic.BuildConfig
import com.starblink.android.basic.config.GuangConfig
import com.starblink.android.basic.ext.toJson
import com.starblink.android.basic.network.base.BaseApiClient
import com.starblink.android.basic.user.UserDataCenter
import com.starblink.android.charles.CharlesConfig
import com.starblink.basic.log.SKLogger
import com.starblink.basic.storage.SkStorage
import com.starblink.basic.util.CommUtils
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import okhttp3.Call
import okhttp3.Callback
import okhttp3.Headers
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response
import okhttp3.logging.HttpLoggingInterceptor
import okio.Buffer
import java.io.IOException
import java.util.Currency
import java.util.Locale
import java.util.TimeZone
import kotlin.collections.set


/**
 * 测试功能管理器
 * （1）数据抓包
 * （2）Mock数据
 */
@Deprecated(message = "封装到base库")
object TestFunctionManager {
    const val TAG = "TestFunctionManager"

    /**true，上传包信息*/
    fun isUploadPacketInfo(): Boolean {
        return SkStorage.getBoolean(CharlesConfig.UploadPacketInfo_KEY, false)
    }

    fun setUploadPacketInfo(animCheckStatus: Boolean) {
        SkStorage.put(CharlesConfig.UploadPacketInfo_KEY, animCheckStatus)
    }

    /**true，Mock包信息*/
    fun isMockPacketInfo(): Boolean {
        return SkStorage.getBoolean(CharlesConfig.MockPacketInfo_KEY, false)
    }

    fun setMockPacketInfo(animCheckStatus: Boolean) {
        SkStorage.put(CharlesConfig.MockPacketInfo_KEY, animCheckStatus)
    }

    private val client = OkHttpClient.Builder()
        .addInterceptor(
            HttpLoggingInterceptor()
                .apply {
                    setLevel(HttpLoggingInterceptor.Level.BODY)
                }).build()

    /**
     * 将接口请求和响应相传至服务器
     */
    fun <D : Operation.Data> uploadApiResponse(
        request: ApolloRequest<D>,
        response: ApolloResponse<D>,
    ) {
        CoroutineScope(Dispatchers.IO).launch {
            // 设置请求参数
            val params = mutableMapOf<String, Any>(
                "business_sence" to "Guang",
                "request_contents_raw" to mapOf(
                    "operationName" to "${request.operation.name()}",
                    "request_contents_raw" to request.operation,
                ),
                "response_contents_raw" to mapOf(
                    "operationName" to "${request.operation.name()}",
                    "response_contents_raw" to response.data
                ),
            )
            request.httpHeaders?.let {
                val headers = mutableMapOf<String, String>()
                it.forEach { headers[it.name] = it.value }
                params["request_headers_raw"] = mapOf(
                    "operationName" to "${request.operation.name()}",
                    "request_headers_raw" to headers
                )
            }
            response.executionContext[HttpInfo]?.let {
                val headers = mutableMapOf<String, String>()
                it.headers.forEach { headers[it.name] = it.value }
                params["response_headers_raw"] = mapOf(
                    "operationName" to "${request.operation.name()}",
                    "response_headers_raw" to headers
                )
                params["response_during"] = it.endMillis - it.startMillis
            }
            val requestBody = params.toJson().toRequestBody("application/json".toMediaTypeOrNull())

            val call = client.newCall(
                Request.Builder()
//                    .url("http://10.118.56.197:8080/app/uploadresponse/insert")
                    .url("http://172.16.83.215:8080/app/uploadresponse/insert")
                    .headers(headerBuilder())
                    .post(requestBody).build()
            )
            try {
                if (call.execute().isSuccessful) {
                    // 上传成功
                    SKLogger.e(TAG, "上传成功123456")
                } else {
                    // 上传失败
                    SKLogger.e(TAG, "上传失败654321")
                }
            } catch (e: IOException) {
                e.printStackTrace()
                SKLogger.e(TAG, e.toString())
            } catch (e: Exception) {
                e.printStackTrace()
                SKLogger.e(TAG, e.toString())
            }
        }
    }

    /**
     * 将接口请求和响应相传至服务器
     */
    fun uploadApiResponse(
        request: Request,
        response: Response,
        tookMs: Long,
    ) {
        // 设置请求参数
        val params = mutableMapOf<String, Any>(
            "business_sence" to "Guang",
        )

        // 参数：request_headers_raw
        val requestHeaders = mutableMapOf<String, String>()
        request.headers.forEach {
            requestHeaders[it.first] = it.second
        }
        params["request_headers_raw"] = requestHeaders

        val requestBody = request.body!!
        var buffer1 = Buffer()
        requestBody.writeTo(buffer1)
        val content1 = buffer1.readString(Charsets.UTF_8)
        params["request_contents_raw"] = JsonParser.parseString(content1)

        val responseHeaders = mutableMapOf<String, String>()
        response.headers.forEach {
            responseHeaders[it.first] = it.second
        }
        params["response_headers_raw"] = responseHeaders

        val content2 = response.peekBody(Long.MAX_VALUE).string()
        params["response_contents_raw"] = JsonParser.parseString(content2)

        params["response_during"] = tookMs

        val realRequestBody =
            params.toJson().toRequestBody("application/json".toMediaTypeOrNull())
        val call = client.newCall(
            Request.Builder()
//                    .url("http://10.118.58.145:8080/app/uploadresponse/insert")
                .url("http://172.16.83.215:8080/app/uploadresponse/insert")
                .headers(headerBuilder())
                .post(realRequestBody).build()
        )
        try {
            call.enqueue(object : Callback {
                override fun onFailure(call: Call, e: IOException) {
                    // 上传成功
                    SKLogger.e(TAG, "上传成功123456")
                }

                override fun onResponse(call: Call, response: Response) {
                    // 上传失败
                    SKLogger.e(TAG, "上传失败654321")
                }
            })
        } catch (e: IOException) {
            e.printStackTrace()
            SKLogger.e(TAG, e.toString())
        } catch (e: Exception) {
            e.printStackTrace()
            SKLogger.e(TAG, e.toString())
        }
    }

    fun reqBindCatch(reqUrl: String, success: () -> Unit, fail: () -> Unit) {
        CoroutineScope(Dispatchers.IO).launch {
            val call = client.newCall(
                Request.Builder()
                    .url(reqUrl)
                    .headers(headerBuilder())
                    .get().build()
            )
            try {
                if (call.execute().isSuccessful) {
                    SKLogger.e(TAG, "reqBindCatch Successful")
                    success.invoke()
                } else {
                    // 上传失败
                    SKLogger.e(TAG, "reqBindCatch error")
                    fail.invoke()
                }
            } catch (e: IOException) {
                e.printStackTrace()
                SKLogger.e(TAG, e.toString())
                fail.invoke()
            } catch (e: Exception) {
                e.printStackTrace()
                SKLogger.e(TAG, e.toString())
                fail.invoke()
            }
        }
    }

    private fun headerBuilder(): Headers {
        return Headers.Builder()
            .add("app_env", BaseApiClient.getCurrSvrCfgEnvName() ?: "")
            .add("app_version", AppUtils.getAppVersionName())
            .add("app_versioncode", AppUtils.getAppVersionCode().toString())
            .add("app_lan", Locale.getDefault().language)
            .add(
                "app_currency",
                EncodeUtils.urlEncode(Currency.getInstance(Locale.getDefault()).getSymbol())
            )
            .add("app_country", UserDataCenter.getLocalCountry())
            .add("platform", "and")
            .add("device_id", "${UserDataCenter.getDeviceId(CommUtils.getContext())}")
            .add("device_type", "${Build.BRAND} ${Build.MODEL}")
            .add(
                "device_screen",
                "${ScreenUtils.getScreenWidth()}*${ScreenUtils.getScreenHeight()}"
            )
            .add("device_os", Build.VERSION.RELEASE)
            .add("device_ip", NetworkUtils.getIPAddress(true))
            .add("build_number", "")
            .add("tz", TimeZone.getDefault().getDisplayName(false, TimeZone.SHORT))
            .build()
    }
}
